package io.renren.modules.com.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.CollectionUtil;
import com.xiaoleilu.hutool.util.NumberUtil;

import io.renren.common.utils.R;
import io.renren.modules.com.dao.ComApportionDao;
import io.renren.modules.com.entity.ComAItemEntity;
import io.renren.modules.com.entity.ComApportionEntity;
import io.renren.modules.com.entity.ComColModel;
import io.renren.modules.com.entity.ComCollectionRecordEntity;
import io.renren.modules.com.entity.ComCrChargingitemEntity;
import io.renren.modules.com.service.ComAItemService;
import io.renren.modules.com.service.ComApportionService;
import io.renren.modules.com.service.ComCollectionRecordService;
import io.renren.modules.com.service.ComCrChargingitemService;

@Service("comApportionService")
public class ComApportionServiceImpl implements ComApportionService {

	@Autowired
	private ComApportionDao comApportionDao;

	@Autowired
	private ComAItemService comAItemService;

	@Autowired
	private ComCrChargingitemService comCrChargingitemService;

	@Autowired
	private ComCollectionRecordService comCollectionRecordService;

	@Override
	public R queryObject(Long serialNo) {
		return queryObjectPrivate(serialNo);
	}

	private R queryObjectPrivate(Long serialNo) {
		ComCrChargingitemEntity comCrChargingitem = comCrChargingitemService.queryObject(serialNo);
		ComCollectionRecordEntity comCollectionRecord = comCollectionRecordService
				.queryObject(comCrChargingitem.getCrSerialNo());
		if (null == comCollectionRecord) {
			return R.error("没有收款记录！");
		}
		ComApportionEntity comApportion = comApportionDao.queryByCrSerialNo(comCollectionRecord.getSerialNo());
		comCollectionRecord.setRemark(comApportion.getRemark());
		List<List<Object>> apportionList = comAItemService.historicalRecords(comCollectionRecord.getSerialNo());
		comCollectionRecord.setApportionList(apportionList);
		return R.ok().put("comCollectionRecord", comCollectionRecord);
	}

	/**
	 * 分摊查询数据
	 */
	@Override
	public List<Map<String, Object>> queryList(Map<String, Object> map) {
		return queryListPrivate(map);
	}

	private List<Map<String, Object>> queryListPrivate(Map<String, Object> map) {
		List<String> itemList = null;
		if (null != map.get("items") && StringUtils.isNotBlank(map.get("items").toString().trim())
				&& !StringUtils.equals("点击选择...", map.get("items").toString().trim())) {
			itemList = new ArrayList<String>(Arrays.asList(map.get("items").toString().replace(" ", "").split(",")));
		} else {
			itemList = itemList();
		}
		map.put("itemList", itemList);
		// 准备查询数据
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date date = new Date();
		String yearMonth = sdf.format(date);
		Date apportionSd = DateUtil.parse(map.get("apportionSd").toString(), sdf);
		Date apportionEd = DateUtil.parse(map.get("apportionEd").toString(), sdf);
		if (apportionSd.after(date)) {
			map.put("alto", map.get("apportionSd"));
		} else {
			map.put("alto", yearMonth);
		}
		if (apportionEd.before(date)) {
			map.put("monument", map.get("apportionEd"));
		} else {
			map.put("monument", yearMonth);
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(apportionSd);
		List<ComCrChargingitemEntity> comCrChargingitemList = comCrChargingitemService.queryList(map);
		if (CollectionUtil.isEmpty(comCrChargingitemList)) {
			return null;
		}
		List<Map<String, Object>> chinaJoy = new ArrayList<Map<String, Object>>();
		Double d = null;
		Double e = null;
		for (ComCrChargingitemEntity comCrChargingitem : comCrChargingitemList) {
			Long crSerialNo = comCrChargingitem.getCrSerialNo();
			map.put("crSerialNo", crSerialNo);
			String item = comCrChargingitem.getChargingItem();
			map.put("item", item);
			ComCollectionRecordEntity comCollectionRecord = comCollectionRecordService.queryObject(crSerialNo);
			Map<String, Object> chinaJoyMap = new HashMap<String, Object>();
			chinaJoyMap.put("serialNo", comCrChargingitem.getSerialNo());
			if (StringUtils.isNotBlank(comCollectionRecord.getAssetIds())) {
				chinaJoyMap.put("assetIds", comCollectionRecord.getAssetIds());
			} else {
				chinaJoyMap.put("assetIds", "");
			}
			if (StringUtils.isNotBlank(comCollectionRecord.getBuildIds())) {
				chinaJoyMap.put("buildIds", comCollectionRecord.getBuildIds());
			} else {
				chinaJoyMap.put("buildIds", "");
			}
			chinaJoyMap.put("billNo", comCollectionRecord.getBillNo());
			chinaJoyMap.put("chargingItem", item);
			if (StringUtils.isNotBlank(comCollectionRecord.getContractNo())) {
				chinaJoyMap.put("contractNo", comCollectionRecord.getContractNo());
			} else {
				chinaJoyMap.put("contractNo", "");
			}
			chinaJoyMap.put("renter", comCollectionRecord.getRenter());
			if (StringUtils.isBlank(comCrChargingitem.getRemark())) {
				chinaJoyMap.put("remark", "");
			} else {
				chinaJoyMap.put("remark", comCrChargingitem.getRemark());

			}
			chinaJoyMap.put("collectionDays", comCollectionRecord.getCollectionDays());
			if (StringUtils.isBlank(comCrChargingitem.getChargingSd())
					|| StringUtils.isBlank(comCrChargingitem.getChargingEd())) {
				chinaJoyMap.put("billingCycle", "");
				chinaJoyMap.put("month", "");
			} else {
				comCrChargingitemService.eclipse(comCrChargingitem, comCollectionRecord, chinaJoyMap);
			}
			chinaJoyMap.put("a", comAItemService.querya(map));
			chinaJoyMap.put("b", comAItemService.queryb(map));
			if (null != comCrChargingitem.getPayAmount()) {
				chinaJoyMap.put("c", comCrChargingitem.getPayAmount());
			} else {
				chinaJoyMap.put("c", "");
			}
			if (null != comAItemService.queryd(map)) {
				d = comAItemService.queryd(map);
				chinaJoyMap.put("d", d);
			} else {
				d = 0.0;
				chinaJoyMap.put("d", "");
			}
			if (null != comAItemService.querye(map)) {
				e = comAItemService.querye(map);
				chinaJoyMap.put("e", e);
			} else {
				e = 0.0;
				chinaJoyMap.put("e", "");
			}
			chinaJoyMap.put("f", NumberUtil.sub(d, e));
			if (null != comAItemService.queryg(map)) {
				chinaJoyMap.put("g", comAItemService.queryg(map));
			} else {
				chinaJoyMap.put("g", "");
			}
			List<ComAItemEntity> comAItemList = comAItemService.queryList(map);
			while (calendar.getTime().before(apportionEd)
					|| StringUtils.equals(sdf.format(calendar.getTime()), sdf.format(apportionEd))) {
				chinaJoyMap.put(sdf.format(calendar.getTime()), "");
				for (ComAItemEntity comAItem : comAItemList) {
					if (!StringUtils.equals(comAItem.getYearMonth(), sdf.format(calendar.getTime()))) {
						continue;
					}
					if (null != comAItem.getJapan()) {
						chinaJoyMap.put(sdf.format(calendar.getTime()), comAItem.getJapan());
					}
					break;
				}
				calendar.add(Calendar.MONTH, 1);
			}
			chinaJoy.add(chinaJoyMap);
			calendar.setTime(apportionSd);
		}
		return chinaJoy;
	}

	private List<String> itemList() {
		List<String> itemList = new ArrayList<String>();
		itemList.add("租金");
		itemList.add("物业费");
		itemList.add("管理费");
		itemList.add("公共能耗费");
		itemList.add("停车费");
		itemList.add("租场费");
		itemList.add("其他");
		return itemList;
	}

	@Override
	public int queryTotal(Map<String, Object> map) {
		return comApportionDao.queryTotal(map);
	}

	@Override
	public void save(ComApportionEntity comApportion) {
		comApportionDao.save(comApportion);
	}

	@Override
	@Transactional
	public void update(ComCollectionRecordEntity comCollectionRecord) {
		Long serialNo = comCollectionRecord.getSerialNo();
		ComCollectionRecordEntity comCollectionRecordEntity = comCollectionRecordService.queryObject(serialNo);
		comCollectionRecordEntity.setShareFlag("2");
		comCollectionRecordService.update(comCollectionRecordEntity);
		ComApportionEntity comApportion = comApportionDao.queryByCrSerialNo(serialNo);
		comApportion.setRemark(comCollectionRecord.getRemark());
		comApportionDao.update(comApportion);
		comAItemService.deleteEVA(serialNo);
		comAItemService.update(comCollectionRecord.getApportionList(), serialNo);
	}

	@Override
	public void delete(Long serialNo) {
		comApportionDao.delete(serialNo);
	}

	public void deleteByCrSerialNo(Long crSerialNo) {
		comApportionDao.deleteByCrSerialNo(crSerialNo);
	}

	@Override
	public void deleteBatch(Long[] serialNos) {
		comApportionDao.deleteBatch(serialNos);
	}

	public void deleteBatchByCrSerialNos(Long[] crSerialNos) {
		comApportionDao.deleteBatchByCrSerialNos(crSerialNos);
	}

	public R initialization() {
		return this.initializationPrivate();
	}

	private R initializationPrivate() {
		Map<String, Object> map = new HashMap<String, Object>();
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		// 初始化分摊开始时间
		Date apportionSd = new Date();
		calendar.setTime(apportionSd);
		calendar.set(Calendar.MONTH, calendar.getActualMinimum(Calendar.MONTH));
		apportionSd = calendar.getTime();
		map.put("apportionSd", sdf.format(apportionSd));
		// 初始化分摊结束时间
		calendar.set(Calendar.MONTH, calendar.getActualMaximum(Calendar.MONTH));
		Date apportionEd = calendar.getTime();
		map.put("apportionEd", sdf.format(apportionEd));
		// 初始化jqgrid表头列名
		map.put("colNames", initializationColNames(apportionSd, apportionEd));
		// 初始化jqgrid表头列名属性
		map.put("colModel", initializationColModel(apportionSd, apportionEd));
		return R.ok(map);
	}

	public R changeJqGrid(String apportionSd, String apportionEd) {
		return this.changeJqGridPrivate(apportionSd, apportionEd);
	}

	private R changeJqGridPrivate(String apportionSd, String apportionEd) {
		Map<String, Object> map = new HashMap<String, Object>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date sd = DateUtil.parse(apportionSd, sdf);
		Date ed = DateUtil.parse(apportionEd, sdf);
		// 初始化jqgrid表头列名
		map.put("colNames", initializationColNames(sd, ed));
		// 初始化jqgrid表头列名属性
		map.put("colModel", initializationColModel(sd, ed));
		return R.ok(map);
	}

	/**
	 * 初始化jqgrid表头列名
	 * 
	 * @param apportionSd
	 * @param apportionEd
	 * @return
	 */
	private List<String> initializationColNames(Date apportionSd, Date apportionEd) {
		List<String> colNames = CollectionUtil.newArrayList("序号", "房号", "楼号", "收款单据", "收款项目", "合同号", "租赁人", "备注",
				"收款日期", "计费周期", "总月数", "已分摊月数", "未分摊月数", "收款金额", "本期应分摊金额", "本期已分摊金额", "本期未分摊金额", "未分摊金额");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(apportionSd);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		while (calendar.getTime().before(apportionEd)
				|| StringUtils.equals(sdf.format(calendar.getTime()), sdf.format(apportionEd))) {
			colNames.add(sdf.format(calendar.getTime()));
			calendar.add(Calendar.MONTH, 1);
		}
		return colNames;
	}

	/**
	 * 初始化jqgrid表头列名属性
	 * 
	 * @param apportionSd
	 * @param apportionEd
	 * @return
	 */
	private List<ComColModel> initializationColModel(Date apportionSd, Date apportionEd) {
		List<ComColModel> colModelList = new ArrayList<ComColModel>();
		// 序号
		ComColModel comColModel = new ComColModel();
		comColModel.setName("serialNo");
		comColModel.setKey(true);
		comColModel.setWidth(80);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		comColModel.setHidden(true);
		colModelList.add(comColModel);
		// 房号
		comColModel = new ComColModel();
		comColModel.setName("assetIds");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 楼号
		comColModel = new ComColModel();
		comColModel.setName("buildIds");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 收款单据
		comColModel = new ComColModel();
		comColModel.setName("billNo");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 收款项目
		comColModel = new ComColModel();
		comColModel.setName("chargingItem");
		comColModel.setWidth(80);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 合同号
		comColModel = new ComColModel();
		comColModel.setName("contractNo");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 租赁人
		comColModel = new ComColModel();
		comColModel.setName("renter");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 备注
		comColModel = new ComColModel();
		comColModel.setName("remark");
		comColModel.setWidth(200);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 收款日期
		comColModel = new ComColModel();
		comColModel.setName("collectionDays");
		comColModel.setWidth(90);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 计费周期
		comColModel = new ComColModel();
		comColModel.setName("billingCycle");
		comColModel.setWidth(200);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 总月数
		comColModel = new ComColModel();
		comColModel.setName("month");
		comColModel.setWidth(70);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 已分摊月数
		comColModel = new ComColModel();
		comColModel.setName("a");
		comColModel.setWidth(90);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 未分摊月数
		comColModel = new ComColModel();
		comColModel.setName("b");
		comColModel.setWidth(90);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 收款金额
		comColModel = new ComColModel();
		comColModel.setName("c");
		comColModel.setWidth(100);
		comColModel.setAlign("right");
		colModelList.add(comColModel);
		// 本期应分摊金额
		comColModel = new ComColModel();
		comColModel.setName("d");
		comColModel.setWidth(110);
		comColModel.setAlign("right");
		colModelList.add(comColModel);
		// 本期已分摊金额
		comColModel = new ComColModel();
		comColModel.setName("e");
		comColModel.setWidth(110);
		comColModel.setAlign("right");
		colModelList.add(comColModel);
		// 本期未分摊金额
		comColModel = new ComColModel();
		comColModel.setName("f");
		comColModel.setWidth(110);
		comColModel.setAlign("right");
		colModelList.add(comColModel);
		// 未分摊金额
		comColModel = new ComColModel();
		comColModel.setName("g");
		comColModel.setWidth(100);
		comColModel.setAlign("right");
		colModelList.add(comColModel);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(apportionSd);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		while (calendar.getTime().before(apportionEd)
				|| StringUtils.equals(sdf.format(calendar.getTime()), sdf.format(apportionEd))) {
			comColModel = new ComColModel();
			comColModel.setName(sdf.format(calendar.getTime()));
			comColModel.setWidth(100);
			comColModel.setAlign("center");
			colModelList.add(comColModel);
			calendar.add(Calendar.MONTH, 1);
		}
		return colModelList;
	}

	public void export(OutputStream out, Map<String, Object> map) {
		exportPrivate(out, map);
	}

	private void exportPrivate(OutputStream out, Map<String, Object> map) {
		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = workbook.createSheet();
		// 生成数字样式
		HSSFCellStyle numberStyle = workbook.createCellStyle();
		numberStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		// 生成文字样式
		HSSFCellStyle style = workbook.createCellStyle();
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		// 生成一个字体
		HSSFFont font = workbook.createFont();
		font.setFontHeightInPoints((short) 12);
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成excel内容
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date sd = DateUtil.parse(map.get("apportionSd").toString(), sdf);
		Date ed = DateUtil.parse(map.get("apportionEd").toString(), sdf);
		// 合并单元格
		List<String> colNames = initializationColNames(sd, ed);
		HSSFRow rowOne = sheet.createRow(0);
		HSSFCell cell = null;
		for (int i = 0; i < colNames.size(); i++) {
			cell = rowOne.createCell(i);
			cell.setCellStyle(style);
			cell.setCellValue(colNames.get(i));
		}
		List<ComColModel> colModel = initializationColModel(sd, ed);
		List<Map<String, Object>> chinaJoy = queryList(map);
		for (int i = 0; i < chinaJoy.size(); i++) {
			Map<String, Object> alphabetBear = chinaJoy.get(i);
			HSSFRow row = sheet.createRow(i + 1);
			for (int j = 0; j < colModel.size(); j++) {
				cell = row.createCell(j);
				if (j < 10) {
					cell.setCellStyle(style);
				}
				if (j >= 10) {
					cell.setCellStyle(numberStyle);
				}
				cell.setCellValue(alphabetBear.get(colModel.get(j).getName()).toString());
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
